<?php

require_once 'Controllers/Room.php';

class Lobby extends Room {

    private $lid;
    private $users;
    private static $instance;

    private function __construct() {
        $this->lid = 0;
        $this->users = array();
        $this->newLobby();
    }

    public function getId() {
        return $this->lid;
    }

    public function getCurrentPlayerName($name = null) {
        if ($name == null) {
            return getUserId();
        } else if ($this->isInLobby($name)) {
            return $name;
        } else {
            $this->AddUser($name);
            return $name;
            //throw new Exception("User $name is not a valid Lobby user.");
        }
    }

    public function getPlayerGender($name = null) {
        return "male";
    }

    private function isInLobby($name) {
        if (isset($this->users[$name])) {
            return true;
        }
//        $db = DBUtils::Create();
//        $users_list = $db->getAllPlayersInRoom($this->lid);
//        foreach ($users_list as $userid) {
//            if ($userid == $name) {
//                return true;
//            }
//        }
        return false;
    }

    public function getPlayersNames($name = null) {
        return $this->getOtherPlayersNames($name);
    }

    public function getOtherPlayersNames($name=null) {
//        $db = DBUtils::Create();
//        $players_list = $db->getAllPlayersInRoom($this->lid);
        $users_list = array();
        $playerName = $this->getCurrentPlayerName($name);
        $current_key = null;
        foreach ($this->users as $key => $value) {
            if ($key != $playerName) {
                $users_list[] = $key;
            }
        }
        return $users_list;
    }

    public function getPhase($name = null) {
        $name = $this->getCurrentPlayerName($name);
        $db = DBUtils::Create();
        return $db->getPhase($name);
    }

    public function setPhase($phase, $name = null) {
        $db = DBUtils::Create();
        $db->setPhase($this->lid, $name, $phase);
        //$this->users[$name] = $phase;
    }

    private function notifyOtherPlayers() {
        $otherNames = $this->getOtherPlayersNames();
        $db = DBUtils::Create();
        foreach ($otherNames as $name) {
            $db->setUniqueid($name);
        }
    }

    public function AddUser($userid) {
        setRoom($this, $userid);
        $this->setPhase(Phase_Available, $userid);
        $this->notifyOtherPlayers();
    }

    public function RemoveUser($userid) {
        unset($this->users[$userid]);
        $db = DBUtils::Create();
        $db->removeFromRoom($this->lid, $userid);
        $this->notifyOtherPlayers();
    }

    private function getBoolParam($param_name) {
        if (isset($_REQUEST[$param_name])) {
            if ($_REQUEST[$param_name] == "true")
                return true;
        }
        return false;
    }

    // Method used to get the lobby singleton.
    public static function GetLobby() {
        if (!isset(self::$instance)) {
            self::$instance = new Lobby();
        }
        self::$instance->loadLobby();
        return self::$instance;
    }

    // used to sync with the db. should be called whenever creating lobby or on checking for changes.
    // no saveLobby exists as every change in the instance should be immediately commited to the db.
    private function loadLobby() {
        $db = DBUtils::Create();
        $db->clearLobby($this->lid);
        $res = $db->loadLobby($this->lid);

        foreach ($res as $user_arr) {
            $this->users[$user_arr[0]] = $user_arr[1];
        }
    }

    // Right now does nothing, as lobby game is allways in the db.
    private function newLobby() {
//        $db = DBUtils::Create();
//        $query = "SELECT gid FROM rooms WHERE gid = $this->lid";
//        $res = $db->run_query($query);
//        if (count($res) == 0) {
//            $query = "INSERT INTO rooms (gid) VALUES ($this->lid)";
//            $db->run_query_no_reply($query);
//        }
    }

    private function generateListDescriptionString($arr) {
        if (!isset($arr)) {
            throw new Exception("NULL reference on generateListDescriptionString");
        }
        if (count($arr) == 0) {
            //throw new Exception("Empty array is an Ilegal parameter in generateListDescriptionString");
            return "";
        }
        $str = $arr[0];
        if (count($arr) == 1) {
            return $str;
        }
        for ($i = 1; $i < count($arr) - 1; $i++) {
            $str .= ", $arr[$i]";
        }
        $str .= " and $arr[$i]";
        return $str;
    }

    public function Invite() {
        $userid = getUserId();
        $name = $this->getCurrentPlayerName(null);
		$my_phase = $this->getPhase();
		if ($my_phase != Phase_Available)
			return null;
		
        $options = array(new Option(1, "Yes"), new Option(2, "No"));
        $gameData = $this->getGameRequestData();

        $otherPlayers = $gameData['other_players'];
        $cards = $gameData['cards'];
        $forceColony = $gameData['force_colony'];
        $forceDarkAges = $gameData['force_darkages'];
        $debugGame = $gameData['debug_game'];
        $decks = $gameData['decks'];

        if (sizeof($decks) == 0) {
            ScreenDisplay::addScreenMessage($this, true, "You must check at least one deck to play with.");
            return null;
        }

        $playersDesc = $this->generateListDescriptionString($otherPlayers);
        $cardsDesc = $this->generateListDescriptionString($cards);

        $message = "Player $name has invited you, $playersDesc to play.
        You will be playing a game with the following cards:$cardsDesc
        Would you like to join?";
        foreach ($otherPlayers as $o_player) {
            MySocket::GetUserReply($this, Input_ChooseOne, $options, 1, 1, null, $message, $o_player, true);
        }

        $replies = MySocket::getUsersReplies($this);
        $accepting = array($name);
        $decline = array();
        foreach ($replies as $other_name => $reply) {
            if ($reply[0] == 'Yes') {
                $accepting[] = $other_name;
            } else {
                $decline[] = $other_name;
            }
        }

        foreach ($decline as $decline_player) {
            $this->setPhase(Phase_Available, $decline_player);
        }

        $game = $this->StartInviteGame($accepting, $decks, $cards, $forceColony, $forceDarkAges, $debugGame);
        if (!$game) {
            ScreenDisplay::addScreenMessage($this, true, "Can not create game with given options, please review and try again");
            return null;
        }

        $this->notifyOtherPlayers();
        return $game;
    }

    private function getGameRequestData() {
        $str_player = "Player_";
        $len_str_player = strlen($str_player);

        $str_card = "Card_";
        $len_str_card = strlen($str_card);

        $required_cards = array();
        $other_players = array();

        //parsing selected players and cards:
        foreach ($_REQUEST as $key => $val) {
            if (substr($key, 0, $len_str_player) == $str_player) {
                $other_players[] = $val;
            } else if (substr($key, 0, $len_str_card) == $str_card) {
                $required_cards[] = $val;
            }
        }
        $allowed_decks = array();

        if ($this->getBoolParam('Basic'))
            $allowed_decks[] = "basic";
        if ($this->getBoolParam('Intrigue'))
            $allowed_decks[] = "intrigue";
        if ($this->getBoolParam('Cornucopia'))
            $allowed_decks[] = "cornucopia";
        if ($this->getBoolParam('Prosperity'))
            $allowed_decks[] = "prosperity";
        if ($this->getBoolParam('Seaside'))
            $allowed_decks[] = "seaside";
        if ($this->getBoolParam('Alchemy'))
            $allowed_decks[] = "alchemy";
        if ($this->getBoolParam('Hinterlands'))
            $allowed_decks[] = "hinterlands";
        if ($this->getBoolParam('DarkAges'))
            $allowed_decks[] = "darkages";
        if ($this->getBoolParam('Guilds'))
            $allowed_decks[] = "guilds";
        if ($this->getBoolParam('Addiction'))
            $allowed_decks[] = "addiction";
        if ($this->getBoolParam('Promotion'))
            $allowed_decks[] = "promotion";

        $forceColony = $this->getBoolParam('forceColony');
        $forceDarkAges = $this->getBoolParam('forceDarkAges');
        $debugGame = $this->getBoolParam('debugGame');


        $res = array('other_players' => $other_players,
            'cards' => $required_cards,
            'force_colony' => $forceColony,
            'force_darkages' => $forceDarkAges,
            'debug_game' => $debugGame,
            'decks' => $allowed_decks
        );
        return $res;
    }

    public function save() {
        
    }

    public function StartInviteGame($players, $decks, $cards, $forceColony, $forceDarkAges, $debugGame) {
        //checkPermissions();
        $game = new Game();
        $lobby = loadLobby();

        //adding this player
        foreach ($players as $playerName) {
            $player = new Player($playerName);
            $game->addPlayer($player);
        }

        $isValidGame = $game->startGame($decks, $cards, $forceColony, $forceDarkAges, $debugGame);
        if (!$isValidGame)
            return null;

        return $game;
    }

    public function getCurrentPlayerTurnNumber($name = null) {
        return 0;
    }

    public function getRoomCardsData($data = array()) {
        $cards_data = array();
        $extenisions = $this->getCardsList();
        $cards = array();
        foreach ($extenisions as $card_list) {
            foreach ($card_list as $card_name) {
                $card = n2c($card_name);
                $cards[] = $card;
            }
        }

        //$aiu = getAlternativeImages($cards);
        foreach ($cards as $card) {
            $cards_data[$card->getValue()] = $card->getFullBasicData(null);
            //$cards_data[$card->getValue()]['alternativeImageUrl'] = $aiu[$card->getKey()];
        }

        return $cards_data;
    }

    public function lobbyData($data = array()) {
        $new_data = array();
        $extenisions = $this->getCardsList();
        $extenisions_names = array_keys($extenisions);
        foreach ($extenisions_names as $extenision_name) {
            $cards = array();
            foreach ($extenisions[$extenision_name] as $card_name) {
                $cards[] = n2c($card_name)->getData(null);
            }
            $new_data[$extenision_name] = $cards;
        }
        return $new_data;
    }

    private function getCardsList() {
        $basicCards = array(
            'Adventurer',
            'Bureaucrat',
            'Cellar',
            'Chancellor',
            'Chapel',
            'Council Room',
            'Feast',
            'Festival',
            'Gardens',
            'Laboratory',
            'Library',
            'Market',
            'Militia',
            'Mine',
            'Moat',
            'Money Lender',
            'Remodel',
            'Smithy',
            'Spy',
            'Thief',
            'Throne Room',
            'Village',
            'Witch',
            'Woodcutter',
            'Workshop'
        );


        $intrigueCards = array(
            'Baron',
            'Bridge',
            'Conspirator',
            'Coppersmith',
            'Courtyard',
            'Duke',
            'Great Hall',
            'Harem',
            'Ironworks',
            'Masquerade',
            'Mining Village',
            'Minion',
            'Nobles',
            'Pawn',
            'Saboteur',
            'Scout',
            'Secret Chamber',
            'Shanty Town',
            'Steward',
            'Swindler',
            'Torturer',
            'Trading Post',
            'Tribute',
            'Upgrade',
            'Wishing Well'
        );

        $cornucopiaCards = array(
            'Fair Grounds',
            'Farming Village',
            'Fortune Teller',
            'Hamlet',
            'Harvest',
            'Horn of Plenty',
            'Horse Traders',
            'Hunting Party',
            'Jester',
            'Menagerie',
            'Remake',
            'Tournament',
            'Young Witch'
        );

        $prosperityCards = array(
            'Bank',
            'Bishop',
            'City',
            'Contraband',
            'Counting House',
            'Expand',
            'Forge',
            'Goons',
            'Grand Market',
            'Hoard',
            'Kings Court',
            'Loan',
            'Mint',
            'Monument',
            'Mountebank',
            'Peddler',
            'Quarry',
            'Rabble',
            'Royal Seal',
            'Talisman',
            'Trade Route',
            'Vault',
            'Venture',
            'Watchtower',
            'Workers Village'
        );

        $seasideCards = array(
            'Ambassador',
            'Bazaar',
            'Caravan',
            'Cutpurse',
            'Embargo',
            'Explorer',
            'Fishing Village',
            'Ghost Ship',
            'Haven',
            'Island',
            'Lighthouse',
            'Lookout',
            'Merchant Ship',
            'Native Village',
            'Navigator',
            'Outpost',
            'Pearl Diver',
            'Pirate Ship',
            'Salvager',
            'Sea Hag',
            'Smugglers',
            'Tactician',
            'Treasure Map',
            'Treasury',
            'Warehouse',
            'Wharf'
        );

        $alchemyCards = array(
            'Alchemist',
            'Apothecary',
            'Apprentice',
            'Familiar',
            'Golem',
            'Herbalist',
            'Philosophers Stone',
            'Possession',
            'Scrying Pool',
            'Transmute',
            'University',
            'Vineyard'
        );

        $promotionCards = array(
            'Black Market',
            'Envoy',
            'Stash',
            'Walled Village',
            'Governor'
        );

        $hinterlandsCards = array(
            'Border Village',
            'Cache',
            'Cartographer',
            'Crossroads',
            'Develop',
            'Duchess',
            'Embassy',
            'Farmland',
            'Fools Gold',
            'Haggler',
            'Highway',
            'Ill-Gotten Gains',
            'Inn',
            'Jack Of All Trades',
            'Mandarin',
            'Margrave',
            'Noble Brigand',
            'Nomad Camp',
            'Oasis',
            'Oracle',
            'Scheme',
            'Silk Road',
            'Spice Merchant',
            'Stables',
            'Trader',
            'Tunnel',
        );

        $addictionCards = array(
            'Blogger',
            'Bundle',
            'Check Point',
            'Cola',
            'Digital Store',
            'Geom',
            'Goat',
            'Gun Shop',
            'Pacifist',
            'Paycheck',
            'Portal',
            'Respawn',
        );

        $darkAgesCards = array(
            "Altar",
            "Armory",
            "Band of Misfits",
            "Bandit Camp",
            "Beggar",
            "Catacombs",
            "Count",
            "Counterfeit",
            "Cultist",
            "Death Cart",
            "Feodum",
            "Forager",
            "Fortress",
            "Graverobber",
            "Hermit",
            "Hunting Grounds",
            "Ironmonger",
            "Junk Dealer",
            "Knights",
            "Marauder",
            "Market Square",
            "Mystic",
            "Pillage",
            "Poor House",
            "Procession",
            "Rats",
            "Rebuild",
            "Rogue",
            "Sage",
            "Scavenger",
            "Squire",
            "Storeroom",
            "Urchin",
            "Vagrant",
            "Wandering Minstrel",
        );

        $guildsCards = array(
            "Advisor",
            "Baker",
            "Butcher",
            "Candlestick Maker",
            "Doctor",
            "Herald",
            "Journeyman",
            "Masterpiece",
            "Merchant Guild",
            "Plaza",
            "Soothsayer",
            "Stonemason",
            "Taxman",
        );

        // $holyGrailCards = array(
        //        "Holy Bomb",
        //      
        //    );

        return array('basic' => $basicCards,
            'intrigue' => $intrigueCards,
            'alchemy' => $alchemyCards,
            'seaside' => $seasideCards,
            'cornucopia' => $cornucopiaCards,
            'prosperity' => $prosperityCards,
            'hinterlands' => $hinterlandsCards,
            'darkages' => $darkAgesCards,
            'addiction' => $addictionCards,
            'promotion' => $promotionCards,
            'guilds' => $guildsCards,
                //  'holygrail' => $holyGrailCards);
        );
    }

}

?>